home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 3794 / 3794.xpi / chrome / content / lib.js < prev    next >
Text File  |  2009-11-16  |  17KB  |  520 lines

  1. /**
  2.  *
  3.  * The source code included in this file is licensed to you by Facebook under
  4.  * the Apache License, Version 2.0.  Accordingly, the following notice
  5.  * applies to the source code included in this file:
  6.  *
  7.  * Copyright ┬⌐ 2009 Facebook, Inc.
  8.  *
  9.  * Licensed under the Apache License, Version 2.0 (the "License"); you may
  10.  * not use this file except in compliance with the License. You may obtain
  11.  * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16.  * License for the specific language governing permissions and limitations
  17.  * under the License.
  18.  *
  19.  */
  20.  
  21.  
  22. var Cc = Components.classes;
  23. var Ci = Components.interfaces;
  24.  
  25. var fbSvc = Cc['@facebook.com/facebook-service;1'].getService(Ci.fbIFacebookService);
  26.  
  27. function debug() {
  28.   if (debug.caller && debug.caller.name) {
  29.     dump(debug.caller.name + ': ');
  30.     logConsole(debug.caller.name + ': ');
  31.   } else {
  32.     dump(' ');
  33.     //logConsole(' ');
  34.   }
  35.   for (var i = 0; i < arguments.length; i++) {
  36.     if (i > 0) dump(', ');
  37.     dump(arguments[i]);
  38.     logConsole(arguments[i]);
  39.   }
  40.   dump('\n');
  41. }
  42.  
  43. var SIDEBAR_AVAILABLE = !!window.toggleSidebar;
  44.  
  45. /* Log message to error console if enableLogging preference is true */
  46. function logConsole (logMessage) {
  47.     var prefSvc = Cc['@mozilla.org/preferences-service;1'].getService(Ci.nsIPrefBranch);
  48.     var debug = prefSvc.getBoolPref('extensions.facebook.debug');
  49.     if (debug) {
  50.         var now = new Date();
  51.         //var logString = "Facebook Toolbar : " + " [" + now + "] " + " \"" + logMessage + "\"";
  52.         var logString = "Facebook Toolbar : " + logMessage;
  53.  
  54.         // send a message to the console
  55.         var consoleService = Cc['@mozilla.org/consoleservice;1'].
  56.                 getService(Ci.nsIConsoleService);
  57.         consoleService.logStringMessage(logString);
  58.     }
  59. }
  60.  
  61. // wrapper for document.getElementById(id).setAttribute(attrib, val) that
  62. // doesn't die if the elem doesn't exist.  useful for us since customize
  63. // toolbar lets you remove a lot of elements.
  64. function setAttributeById(id, attrib, val) {
  65.     var el = document.getElementById(id);
  66.     if (el) {
  67.       el.setAttribute(attrib, val);
  68.       return true;
  69.     }
  70.     return false;
  71. }
  72.  
  73. function getAttributeById(id, attrib) {
  74.     var el = document.getElementById(id);
  75.     if (el) {
  76.       return el.getAttribute(attrib);
  77.     }
  78.     return false;
  79. }
  80.  
  81. function SetFacebookStatus(status) {
  82.     if (fbSvc.canSetStatus) {
  83.         fbSvc.setStatus(status.value);
  84.         status.blur();
  85.     } else {
  86.         var authorizeUrl = "http://www.facebook.com/authorize.php?api_key="+fbSvc.apiKey
  87.             +"&v=1.0&ext_perm=status_update";
  88.         fbSvc.clearCanSetStatus();
  89.         openUILink(authorizeUrl);
  90.     }
  91.     return false;
  92. }
  93.  
  94. function OpenFBUrl(page, uid, e, params) {
  95.   var url = 'http://www.facebook.com/' + page + '?id=' + uid + '&src=fftb';
  96.   if( params ) {
  97.     for ( var param in params ) {
  98.         url += '&' + param + '=';
  99.         if( null != params[params] ) url += params[param];
  100.     }
  101.   }
  102.   debug('Opening ' + url);
  103.   openUILink(url, e);
  104.   e.stopPropagation();
  105.   return false;
  106. }
  107.  
  108. function IsSidebarOpen() {
  109.   return SIDEBAR_AVAILABLE &&
  110.     (top.document.getElementById('viewFacebookSidebar').getAttribute('checked') == 'true');
  111. }
  112.  
  113. function GetFriendsListElement() {
  114.   var list = IsSidebarOpen()
  115.       ? top.document.getElementById('sidebar').contentDocument.getElementById('SidebarFriendsList')
  116.       : null;
  117.   return list || top.document.getElementById('PopupFacebookFriendsList');
  118. }
  119.  
  120. function GetFBSearchBox() {
  121.   var box = top.document.getElementById('facebook-search');
  122.   if (!box && SIDEBAR_AVAILABLE) {
  123.     box = top.document.getElementById('sidebar').contentDocument.getElementById('facebook-search-sidebar');
  124.   }
  125.   return box;
  126. }
  127.  
  128. function SelectItemInList(item, list) {
  129.   if (!facebook) {
  130.     // this must have been called via the sidebar
  131.     list.selectedItem = item;
  132.   } else {
  133.     // for some reason, calling hidePopup followed by showPopup
  134.     // results in the popup being hidden!
  135.     // so we need to disable the hidePopup call temporarily while the
  136.     // focus shifts around
  137.     facebook.ignoreBlur = true;
  138.     list.selectedItem = item;
  139.     GetFBSearchBox().focus();
  140.     facebook.ignoreBlur = false;
  141.   }
  142. }
  143.  
  144. function SetSpecificHint(doc, visible, text, oncommand) {
  145.   var hint = doc.getElementById('FacebookHint');
  146.   if (hint) {
  147.     if (visible) {
  148.       hint.setAttribute('oncommand', oncommand);
  149.       doc.getElementById('FacebookHintText').setAttribute('value', text);
  150.       hint.style.display = '';
  151.     } else {
  152.       hint.style.display = 'none';
  153.     }
  154.   }
  155. }
  156.  
  157. function SetHint(visible, text, oncommand) {
  158.   if (IsSidebarOpen()) {
  159.     var doc = top.document.getElementById('sidebar').contentDocument;
  160.     SetSpecificHint(doc, visible, text, oncommand);
  161.   }
  162.   SetSpecificHint(document, visible, text, oncommand);
  163. }
  164.  
  165. function SearchFriends(search) {
  166.   debug('searching for: ' + search);
  167.   var sidebar = IsSidebarOpen();
  168.   var list = GetFriendsListElement();
  169.   if (list.firstChild.id == 'FacebookHint') return; // not logged in
  170.   var numMatched = 0;
  171.   var lastDisplayed = null;
  172.   var searches = [];
  173.   if (search) {
  174.     for each (var s in search.split(/\s+/)) {
  175.       if (s) {
  176.         searches.push(new RegExp('\\b' + s, 'i'));
  177.       }
  178.     }
  179.   }
  180.   for (var i = 0; i < list.childNodes.length; i++) {
  181.     var node = list.childNodes[i];
  182.     var sname = node.getAttribute('friendname');
  183.     if (!sname) continue;
  184.     if (!search || searches.every(function(s) { return s.test(sname); })) {
  185.       if (sidebar || (numMatched < 4 && search)) {
  186.         node.style.display = '';
  187.         lastDisplayed = node;
  188.       } else {
  189.         node.style.display = 'none';
  190.       }
  191.       numMatched++;
  192.     } else {
  193.       node.style.display = 'none';
  194.     }
  195.   }
  196.   debug('matched', numMatched);
  197.   if (search && numMatched == 0) {
  198.     SetHint(true, 'Press enter to search for "' + search + '" on Facebook',
  199.             "openUILink('http://www.facebook.com/search/?src=fftb&q=' + encodeURIComponent(GetFBSearchBox().value), event);");
  200.   } else if (!sidebar && (numMatched > 4 || !search)) {
  201.     var str = 'See all ' + numMatched + ' friends';
  202.     if (search)
  203.       str += ' matching "' + search + '"';
  204.     str += '...';
  205.     SetHint(true, str, "toggleSidebar('viewFacebookSidebar');");
  206.   } else {
  207.     SetHint(false, '', '');
  208.   }
  209.   if (!sidebar) {
  210.       var msger = document.getElementById('PopupMessager'),
  211.           poker = document.getElementById('PopupPoker'),
  212.           poster = document.getElementById('PopupPoster');
  213.       if (1 == numMatched) {
  214.           var uid = lastDisplayed.getAttribute('userid'),
  215.               firstname = lastDisplayed.getAttribute('firstname');
  216.           msger.setAttribute('userid', uid );
  217.           msger.setAttribute('value', 'Send ' + firstname + ' a message');
  218.  
  219.           poker.setAttribute('userid', uid );
  220.           poker.setAttribute('value', 'Poke ' + firstname );
  221.  
  222.           poster.setAttribute('userid', uid);
  223.           poster.setAttribute('value', 'Write on ' + firstname + "'s wall");
  224.  
  225.           msger.style.display = poker.style.display = poster.style.display = '';
  226.       } else {
  227.           msger.style.display = poker.style.display = poster.style.display = 'none';
  228.       }
  229.   }
  230.   var item = list.selectedItem;
  231.   if (item) {
  232.     if (item.style.display == 'none') {
  233.       list.selectedIndex = -1;
  234.     } else {
  235.       list.ensureElementIsVisible(item);
  236.     }
  237.   }
  238. }
  239.  
  240. function HandleKeyPress(e) {
  241.   var list = GetFriendsListElement();
  242.   switch (e.keyCode) {
  243.     case e.DOM_VK_UP:
  244.       MoveInList('previousSibling');
  245.       e.stopPropagation();
  246.       e.preventDefault();
  247.       return;
  248.     case e.DOM_VK_DOWN:
  249.       MoveInList('nextSibling');
  250.       e.stopPropagation();
  251.       e.preventDefault();
  252.       return;
  253.     case e.DOM_VK_RETURN: // fall-through
  254.     case e.DOM_VK_ENTER:
  255.       var item = list.selectedItem;
  256.       if (item && item.style.display != 'none') {
  257.         item.doCommand();
  258.       } else {
  259.         openUILink('http://www.facebook.com/search/?src=fftb&q=' +
  260.                    encodeURIComponent(GetFBSearchBox().value), e);
  261.       }
  262.       // fall-through to hide the pop-up...
  263.     case e.DOM_VK_ESCAPE:
  264.       // for some reason calling blur() doesn't work here...lets just
  265.       // focus the browser instead
  266.       content.focus();
  267.       return;
  268.   }
  269. }
  270.  
  271. function MoveInList(dir) {
  272.   var list = GetFriendsListElement();
  273.   var item = list.selectedItem;
  274.   if (!item || item.style.display == 'none') {
  275.     // nothing selected yet, start at the top...
  276.     if (dir == 'previousSibling') {
  277.       item = list.lastChild;
  278.     } else {
  279.       item = list.firstChild;
  280.     }
  281.   } else {
  282.     // start by moving up/down one
  283.     item = item[dir];
  284.   }
  285.   while (item && item.style.display == 'none') {
  286.     item = item[dir];
  287.   }
  288.  
  289.   if (item) {
  290.     SelectItemInList(item, list);
  291.   }
  292. }
  293.  
  294. function FacebookLogin() {
  295.   if (fbSvc.loggedIn) {
  296.     dump('logging out\n');
  297.     fbSvc.sessionEnd();
  298.     var req = new XMLHttpRequest();
  299.     req.open('post', 'http://www.facebook.com/logout.php');
  300.     req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  301.     req.send('confirm=1');
  302.   } else {
  303.     // popup login page height is at most 500, but add 20 pixels for the
  304.     // button we show at the bottom of the page
  305.     window.open('chrome://facebook/content/login.xul', '',
  306.                 'chrome,centerscreen,width=646,height=520,modal=yes,dialog=yes,close=yes');
  307.   }
  308. }
  309.  
  310. function RenderStatusMsg(msg) {
  311.     msg = msg.replace(/\s*$/g, '');
  312.     if (msg && '.?!\'"'.indexOf(msg[msg.length-1]) == -1) {
  313.         msg = msg.concat('.');
  314.     }
  315.     return msg;
  316. }
  317.  
  318. function SetProfileTime(item, time){
  319.   item.setAttribute('ptime',getProfileTime(time));
  320. }
  321.  
  322. function SetStatus(item, status, time) {
  323.     if (status) {
  324.         var firstName = item.getAttribute('firstname');
  325.         var msg = firstName + ' ' + RenderStatusMsg(status);
  326.         if (item.firstChild) {
  327.             item.firstChild.nodeValue = msg;
  328.         } else {
  329.             item.appendChild(document.createTextNode(msg));
  330.         }
  331.         item.setAttribute('stime', getStatusTime(time));
  332.     } else {
  333.         if (item.firstChild) {
  334.             item.removeChild(item.firstChild);
  335.         }
  336.         item.removeAttribute('stime');
  337.     }
  338. }
  339.  
  340. function DatesInSeconds() {
  341.   this.minute  = 60;
  342.   this.two_mins= 120;
  343.   this.hour    = 60*this.minute;
  344.   this.hour_and_half = 90*this.minute;
  345.   this.day     = 24*this.hour;
  346.   this.week    = 7*this.day;
  347.   this.month   = 30.5*this.day;
  348.   this.year    = 365*this.day;
  349. }
  350. var dates_in_seconds = new DatesInSeconds();
  351.  
  352. /*
  353.  * Render a short version of the date depending on how close it is to today's date
  354.  * @param time - time in seconds from epoch
  355.  * XXX - If this comes back to life, make sure it is locale friendly
  356.  */
  357. /*
  358. function getRelativeTime(time) {
  359.   var elapsed   = Math.floor(new Date().getTime()/1000) - time;
  360.   if (elapsed <= 1)
  361.     return 'a moment ago';
  362.   if (elapsed < dates_in_seconds.minute)
  363.     return elapsed.toString() + ' seconds ago';
  364.   if (elapsed < 2*dates_in_seconds.two_mins)
  365.     return 'one minute ago';
  366.   if (elapsed < dates_in_seconds.hour)
  367.     return Math.floor(elapsed/dates_in_seconds.minute) + ' minutes ago';
  368.   if (elapsed < dates_in_seconds.hour_and_half)
  369.     return 'about an hour ago';
  370.   if (elapsed < dates_in_seconds.day )
  371.     return Math.round(elapsed/dates_in_seconds.hour) + ' hours ago';
  372.   if (elapsed < dates_in_seconds.week) {
  373.     var days    = new Array( "Sunday", "Monday", "Tuesday", "Wednesday",
  374.                              "Thursday", "Friday", "Saturday" );
  375.     var d       = new Date;
  376.     d.setTime(time*1000);
  377.     return 'on ' + days[d.getDay()];
  378.   }
  379.   if (elapsed < dates_in_seconds.week*1.5)
  380.     return 'about a week ago';
  381.   if (elapsed < dates_in_seconds.week*3.5)
  382.     return 'about ' + Math.round(elapsed/dates_in_seconds.week) + ' weeks ago';
  383.   if (elapsed < dates_in_seconds.month*1.5)
  384.     return 'about a month ago';
  385.   if (elapsed < dates_in_seconds.year)
  386.     return 'about ' + Math.round(elapsed/dates_in_seconds.month) + ' months ago';
  387.   return 'over a year ago';
  388. }*/
  389.  
  390. function getRelTime(time, isProfile) {
  391.   var sbundle = GetFBStringBundle();
  392.   var elapsed   = Math.floor(new Date().getTime()/1000) - time;
  393.   if( elapsed < dates_in_seconds.week )
  394.     return getRelTimeWithinWeek(time, false, isProfile);
  395.   if (elapsed < dates_in_seconds.week*1.5)
  396.     return sbundle.getString('aboutaweekago');
  397.   if (elapsed < dates_in_seconds.week*3.5) {
  398.     var weeksElapsed = Math.round(elapsed/dates_in_seconds.week);
  399.     if (weeksElapsed == 2)
  400.       return sbundle.getString('abouttwoweeksago');
  401.     else
  402.       return sbundle.getFormattedString('aboutweeksago', [weeksElapsed]);
  403.   }
  404.   if (elapsed < dates_in_seconds.month*1.5)
  405.     return sbundle.getString('aboutamonthago');
  406.   return ''; //XX Brian - Why are we returning here?
  407.  
  408.   if (elapsed < dates_in_seconds.year) {
  409.     var monthsElapsed = Math.round(elapsed/dates_in_seconds.month);
  410.     if (monthsElapsed == 2)
  411.       return sbundle.getString('abouttwomonthsago');
  412.     else
  413.       return sbundle.getFormattedString('aboutmonthsago', [monthsElapsed]);
  414.   }
  415.   return sbundle.getString('overayear');
  416. }
  417.  
  418. function getProfileTime(profile_time) {
  419.   var relative_time = getRelTime(profile_time, true);
  420.   var sbundle = GetFBStringBundle();
  421.   var updatedProfileTime = sbundle.getFormattedString('updatedProfileTime', [relative_time]);
  422.   return relative_time ? updatedProfileTime : '';
  423. }
  424.  
  425. function getRelTimeWithinWeek(time, initialCap, isProfile) {
  426.   var currentTime = new Date;
  427.  
  428.   var updateTime = new Date;
  429.   updateTime.setTime(time*1000);
  430.  
  431.   var sbundle = GetFBStringBundle();
  432.  
  433.   var mon, tues, wed, thurs, fri, sat, sun;
  434.   if (isProfile) {
  435.     mon = sbundle.getString('mondayInSentence');
  436.     tues = sbundle.getString('tuesdayInSentence');
  437.     wed = sbundle.getString('wednesdayInSentence');
  438.     thurs = sbundle.getString('thursdayInSentence');
  439.     fri = sbundle.getString('fridayInSentence');
  440.     sat = sbundle.getString('saturdayInSentence');
  441.     sun = sbundle.getString('sundayInSentence');
  442.   }
  443.   else {
  444.     mon = sbundle.getString('monday');
  445.     tues = sbundle.getString('tuesday');
  446.     wed = sbundle.getString('wednesday');
  447.     thurs = sbundle.getString('thursday');
  448.     fri = sbundle.getString('friday');
  449.     sat = sbundle.getString('saturday');
  450.     sun = sbundle.getString('sunday');
  451.   }
  452.   var yesterday = sbundle.getString('yesterday');
  453.   var yesterdayic = sbundle.getString('yesterdayic');
  454.   var today = sbundle.getString('today');
  455.   var todayic = sbundle.getString('todayic');
  456.   var days = new Array(sun, mon, tues, wed, thurs, fri, sat);
  457.   var day;
  458.   var recently = true;
  459.  
  460.   // assumption that status messages are only shown if in the last 7 days
  461.   if (updateTime.getDate() == currentTime.getDate()) {
  462.     day = initialCap ? todayic : today;
  463.   } else if ((updateTime.getDay() + 1) % 7 == currentTime.getDay()) {
  464.     day = initialCap ? yesterdayic : yesterday;
  465.   } else {
  466.     day = days[updateTime.getDay()];
  467.     recently = false;
  468.   }
  469.  
  470.   var hour = updateTime.getHours();
  471.  
  472.   var minute = updateTime.getMinutes();
  473.   if (minute < 10) {
  474.     minute = '0' + minute;
  475.   }
  476.  
  477.   var tstr;
  478.   if (recently)
  479.     tstr = sbundle.getFormattedString('timeStringRecent', [day, hour, minute]);
  480.   else
  481.     tstr = sbundle.getFormattedString('timeStringDay', [day, hour, minute]);
  482.  
  483.   return tstr;
  484. }
  485.  
  486. function getStatusTime(status_time) {
  487.   return getRelTimeWithinWeek(status_time, true, false);
  488. }
  489.  
  490. /**
  491.  * This is called on _every_ page loaded in Firefox
  492.  * and tests whether it's a Facebook URL. So it better be as
  493.  * efficient as possible
  494.  */
  495. function IsFacebookLocation(location) {
  496.   if( location && location.schemeIs // use to detect nsIURI
  497.     && ( location.schemeIs("http") || location.schemeIs("https") ) ) {
  498.     var len = location.host.length;
  499.     return (len>=12) && ("facebook.com" == location.host.substring(len-12));
  500.   }
  501.   return false;
  502. }
  503.  
  504. // Toggles the toolbar
  505. function facebook_toggleToolbar()
  506. { /* modelled on webdeveloper toolbar behavior */
  507.     var toolbar = document.getElementById("facebook-toolbar");
  508.     toolbar.collapsed = !toolbar.collapsed;
  509.     document.persist("facebook-toolbar", "collapsed");
  510. }
  511.  
  512. function GetFBStringBundle() {
  513.   var sb = document.getElementById('facebook-strings');
  514.   if (!sb && SIDEBAR_AVAILABLE) {
  515.     debug( "getting bundle from sidebar..." );
  516.     sb = document.getElementById('sidebar').contentDocument.getElementById('facebook-strings');
  517.   }
  518.   return sb;
  519. }
  520.